package com.hotacorp.opencloud.authserver.granter;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;

import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.OAuth2Request;
import org.springframework.security.oauth2.provider.OAuth2RequestFactory;
import org.springframework.security.oauth2.provider.TokenRequest;
import org.springframework.security.oauth2.provider.token.AbstractTokenGranter;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;

import com.hotacorp.opencloud.authserver.service.EnhanceUserDetailsService;

/**
 * 新增手机号、短信验证码登录处理，当需要用短信验证码验证时，authorized_grant_types应该包含smscode
 * @author lwg
 *
 */
public class PhoneSMSTokenGranter extends AbstractTokenGranter {
	private static final String GRANT_TYPE = "smscode";
	private static final String SMS_OAUTH_KEY = "sms:oauth";
	
	private EnhanceUserDetailsService myUserDetailsService;
	private StringRedisTemplate stringRedisTemplate;

	public PhoneSMSTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory, EnhanceUserDetailsService myUserDetailsService, StringRedisTemplate stringRedisTemplate) {
		super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE);
		this.myUserDetailsService = myUserDetailsService;
		this.stringRedisTemplate = stringRedisTemplate;
	}

	@Override
	protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {
        Map<String, String> parameters = new LinkedHashMap<>(tokenRequest.getRequestParameters());
        String clientId = parameters.get("client_id");
        String phone = parameters.get("phone");
        String smscode = parameters.get("smscode");
        String validsmscodeString = stringRedisTemplate.boundValueOps(SMS_OAUTH_KEY + ":" + clientId + ":" + phone).get();
        if (!Objects.equals(smscode, validsmscodeString)) {
        	throw new InvalidGrantException("验证码错误！");
        }
        
        UserDetails details = myUserDetailsService.loadUserByPhone(phone);
        if (details == null) {
            throw new InvalidGrantException("无法获取用户信息");
        }
        stringRedisTemplate.delete(SMS_OAUTH_KEY + ":" + clientId + ":" + phone);
        Authentication userAuth = new UsernamePasswordAuthenticationToken(details, null, details.getAuthorities());
        ((AbstractAuthenticationToken) userAuth).setDetails(parameters);
		OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest);		
		return new OAuth2Authentication(storedOAuth2Request, userAuth);
	}
}
